package org.jsola.hr.common.oneKeyPay;

import kong.unirest.HttpResponse;
import kong.unirest.Unirest;
import lombok.extern.slf4j.Slf4j;
import okhttp3.HttpUrl;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.security.*;
import java.security.cert.*;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.util.Base64;

/**
 * 微信批量支付相关方法
 * @author wu
 */
@Slf4j
public class VXpay {

    // 商户的 商户号
    private static String mchid = "1615112360";


    public static void main(String[] args) throws IOException, IllegalBlockSizeException, NoSuchAlgorithmException, SignatureException, InvalidKeyException, BadPaddingException {

        String name = rsaEncryptOAEP("吴鸿",
                getCertificate("D:\\payWX\\wx_key\\wechatpay_249422CB735324ABDD7B9E0800217510B922B483.pem"));

//        String authorization = getToken("POST", HttpUrl.parse("https://api.mch.weixin.qq.com/v3/partner-transfer/batches"),
//                "{\n" +
//                        "  \"sub_mchid\": \"1615112360\",\n" +
//                        "  \"authorization_type\": \"FUND_AUTHORIZATION_TYPE\",\n" +
//                        "  \"out_batch_no\": \"2021101410442154whahy10\",\n" +
//                        "  \"batch_name\": \"批量转账\",\n" +
//                        "  \"batch_remark\": \"批量转账的备注\",\n" +
//                        "  \"total_amount\": 100,\n" +
//                        "  \"total_num\": 1,\n" +
//                        "  \"transfer_detail_list\": [\n" +
//                        "    {\n" +
//                        "      \"out_detail_no\": \"wuhong2021102017100010\",\n" +
//                        "      \"transfer_amount\": 100,\n" +
//                        "      \"transfer_remark\": \"批量转账到零钱\",\n" +
//                        "      \"openid\": \"o2zS4wBzqxJcT1wUYOcxNGCLnZwo\",\n" +
//                        "      \"user_name\": \""+name+"\"\n" +
//                        "    }\n" +
//                        "  ],\n" +
//                        "  \"sp_appid\": \"wx6e84b644eff334b4\",\n" +
//                        "  \"transfer_purpose\": \"COMMISSION\",\n" +
//                        "  \"transfer_scene\": \"PAYROLL_CARD_TRANSFER\"\n" +
//                        "}");
//
//        System.out.println("===================================");
//        System.out.println(authorization);
//        System.out.println("===================================");
//        HttpResponse<String> socResponse = Unirest.post("https://api.mch.weixin.qq.com/v3/partner-transfer/batches")
//                .header("Content-Type", "application/json")
//                .header("Authorization", authorization)
//                .header("User-Agent", "zhixinren/1.0")
//                .header("Accept", "*/*")
//                .header("Wechatpay-Serial", "249422CB735324ABDD7B9E0800217510B922B483")
//                .body("{\n" +
//                        "  \"sub_mchid\": \"1615112360\",\n" +
//                        "  \"authorization_type\": \"FUND_AUTHORIZATION_TYPE\",\n" +
//                        "  \"out_batch_no\": \"2021101410442154whahy10\",\n" +
//                        "  \"batch_name\": \"批量转账\",\n" +
//                        "  \"batch_remark\": \"批量转账的备注\",\n" +
//                        "  \"total_amount\": 100,\n" +
//                        "  \"total_num\": 1,\n" +
//                        "  \"transfer_detail_list\": [\n" +
//                        "    {\n" +
//                        "      \"out_detail_no\": \"wuhong2021102017100010\",\n" +
//                        "      \"transfer_amount\": 100,\n" +
//                        "      \"transfer_remark\": \"批量转账到零钱\",\n" +
//                        "      \"openid\": \"o2zS4wBzqxJcT1wUYOcxNGCLnZwo\",\n" +
//                        "      \"user_name\": \""+name+"\"\n" +
//                        "    }\n" +
//                        "  ],\n" +
//                        "  \"sp_appid\": \"wx6e84b644eff334b4\",\n" +
//                        "  \"transfer_purpose\": \"COMMISSION\",\n" +
//                        "  \"transfer_scene\": \"PAYROLL_CARD_TRANSFER\"\n" +
//                        "}")
//                .asString();
//        System.out.println(socResponse.getBody());
        // 微信批次号查询批次信息
//        authorization = getToken("GET",
//                HttpUrl.parse("https://api.mch.weixin.qq.com/v3/partner-transfer/batches/batch-id/1030001067701157235952021102100462855838?need_query_detail=true&limit=100&detail_status=ALL"),
//                "");
//        System.out.println("===================================");
//        System.out.println(authorization);
//        System.out.println("===================================");
//                HttpResponse<String> socResponse = Unirest.get("https://api.mch.weixin.qq.com/v3/partner-transfer/batches/batch-id/1030001067701157235952021102100462855838?need_query_detail=true&limit=100&detail_status=ALL")
//                .header("Content-Type", "application/json")
//                .header("Authorization", authorization)
//                .header("User-Agent", "zhixinren/1.0")
//                .header("Accept", "*/*")
//                .header("Wechatpay-Serial", "249422CB735324ABDD7B9E0800217510B922B483").asString();
//        System.out.println(socResponse.getBody());
        // 微信批次号 + 微信批次明细号 查询详细信息
//        authorization = getToken("GET",
//                HttpUrl.parse("https://api.mch.weixin.qq.com/v3/partner-transfer/batches/batch-id/1030001067701157235952021102100462855838/details/detail-id/1040001067701157235952021102100461572757"),
//                "");
//        System.out.println("===================================");
//        System.out.println(authorization);
//        System.out.println("===================================");
//        HttpResponse<String> socResponse = Unirest.get("https://api.mch.weixin.qq.com/v3/partner-transfer/batches/batch-id/1030001067701157235952021102100462855838/details/detail-id/1040001067701157235952021102100461572757")
//                .header("Content-Type", "application/json")
//                .header("Authorization", authorization)
//                .header("User-Agent", "zhixinren/1.0")
//                .header("Accept", "*/*")
//                .header("Wechatpay-Serial", "249422CB735324ABDD7B9E0800217510B922B483").asString();
//        System.out.println(socResponse.getBody());


        // 解密
//        String namecc = "kW7Nn2vGV/BoQ7983E2XC4Db2uQ4H8J4fmHDjhqUwc/d59W6e/gBrh6Z6aDTInv4E6qH+rW14xiebFDu4ilbICTkNAQsca26Qe4FzbHaiFf2kmDjxFwcJCyX30MUOM0QepYVX4zHpV38ZxUYdse5gQzGd4DDqGw1A2Tg/1mySZDycP/xdsqwOxpI+iTerYTSB/cH1T7YQIBuaZqoiGL5+oqy142WFL+RmoKCEpIkrfKNZj/vU6lr7uVefi5dIV+S4wpnp9gUyCzZlXZdyXdj3i9iucI7vWiXlk/AumfE86hZEguYPW8bYqX6CIHutXJr09QOxBt3vdI1s06W82nu6Q==";
//        String namecch = rsaDecryptOAEP(namecc, yourPrivateKey);
//        System.out.println(namecch);
        // 查询授权状态
        String authorization = getToken("GET",
                HttpUrl.parse("https://api.mch.weixin.qq.com/v3/payroll-card/relations/oV7BD6lvGyU5fkYI9m7oQnNLzDCI?sub_mchid=1615112360&appid=wx96ec12f2148c28f5"),
                "");
        System.out.println("===================================");
        System.out.println(authorization);
        System.out.println("===================================");
        HttpResponse<String> socResponse = Unirest.get("https://api.mch.weixin.qq.com/v3/payroll-card/relations/oV7BD6lvGyU5fkYI9m7oQnNLzDCI?sub_mchid=1615112360&appid=wx96ec12f2148c28f5")
                .header("Content-Type", "application/json")
                .header("Authorization", authorization)
                .header("User-Agent", "zhixinren/1.0")
                .header("Accept", "*/*")
                .header("Wechatpay-Serial", "249422CB735324ABDD7B9E0800217510B922B483").asString();
        System.out.println(socResponse.getBody());

    }


    /**
     * 通过证书加密敏感信息
     *
     * @param message     需要加密的信息
     * @param certificate 证书（通过下面的方法获取）
     * @return 加密后的str
     * @throws IllegalBlockSizeException 异常
     * @throws IOException               异常
     */
    public static String rsaEncryptOAEP(String message, X509Certificate certificate)
            throws IllegalBlockSizeException, IOException {
        try {
            Cipher cipher = Cipher.getInstance("RSA/ECB/OAEPWithSHA-1AndMGF1Padding");
            cipher.init(Cipher.ENCRYPT_MODE, certificate.getPublicKey());

            byte[] data = message.getBytes(StandardCharsets.UTF_8);
            byte[] cipherdata = cipher.doFinal(data);
            return Base64.getEncoder().encodeToString(cipherdata);
        } catch (NoSuchAlgorithmException | NoSuchPaddingException e) {
            throw new RuntimeException("当前Java环境不支持RSA v1.5/OAEP", e);
        } catch (InvalidKeyException e) {
            throw new IllegalArgumentException("无效的证书", e);
        } catch (IllegalBlockSizeException | BadPaddingException e) {
            throw new IllegalBlockSizeException("加密原串的长度不能超过214字节");
        }
    }

    /**
     * 获取证书。
     *
     * @param filename 证书文件路径  (required)
     * @return X509证书
     */
    public static X509Certificate getCertificate(String filename) throws IOException {
        InputStream fis = new FileInputStream(filename);
        try (BufferedInputStream bis = new BufferedInputStream(fis)) {
            CertificateFactory cf = CertificateFactory.getInstance("X509");
            X509Certificate cert = (X509Certificate) cf.generateCertificate(bis);
            cert.checkValidity();
            return cert;
        } catch (CertificateExpiredException e) {
            throw new RuntimeException("证书已过期", e);
        } catch (CertificateNotYetValidException e) {
            throw new RuntimeException("证书尚未生效", e);
        } catch (CertificateException e) {
            throw new RuntimeException("无效的证书文件", e);
        }
    }


    private static String schema = "WECHATPAY2-SHA256-RSA2048";
    //    HttpUrl httpurl = HttpUrl.parse(url);
    // 服务商的商户号
    private static String yourMerchantId = "1579540071";
    // 服务商的证书序列号
    private static String yourCertificateSerialNo = "3E90DFBC59C06337C19C9124B353C468051A88AF";
    // 服务商的key
    private static PrivateKey yourPrivateKey = null;

    static {
        try {
            yourPrivateKey = getPrivateKey("D:\\payWX\\服务商相关\\1579540071_20211020_cert\\apiclient_key.pem");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public static String getToken(String method, HttpUrl url, String body)
            throws SignatureException, NoSuchAlgorithmException, IOException, InvalidKeyException {
        String nonceStr = "2021101410442154whahy01";
        long timestamp = System.currentTimeMillis() / 1000;
        String message = buildMessage(method, url, timestamp, nonceStr, body);
        String signature = sign(message.getBytes(StandardCharsets.UTF_8));

        return schema + "\n"
                + "mchid=\"" + yourMerchantId + "\","
                + "nonce_str=\"" + nonceStr + "\","
                + "timestamp=\"" + timestamp + "\","
                + "serial_no=\"" + yourCertificateSerialNo + "\","
                + "signature=\"" + signature + "\"";
    }

    public static String sign(byte[] message) throws NoSuchAlgorithmException, SignatureException, IOException, InvalidKeyException {
        Signature sign = Signature.getInstance("SHA256withRSA");
        sign.initSign(yourPrivateKey);
        sign.update(message);

        return Base64.getEncoder().encodeToString(sign.sign());
    }

    public static String buildMessage(String method, HttpUrl url, long timestamp, String nonceStr, String body) {
        String canonicalUrl = url.encodedPath();
        if (url.encodedQuery() != null) {
            canonicalUrl += "?" + url.encodedQuery();
        }

        return method + "\n"
                + canonicalUrl + "\n"
                + timestamp + "\n"
                + nonceStr + "\n"
                + body + "\n";
    }

    /**
     * 获取私钥。
     *
     * @param filename 私钥文件路径  (required)
     * @return 私钥对象
     */
    public static PrivateKey getPrivateKey(String filename) throws IOException {

        String content = new String(Files.readAllBytes(Paths.get(filename)), StandardCharsets.UTF_8);
        try {
            String privateKey = content.replace("-----BEGIN PRIVATE KEY-----", "")
                    .replace("-----END PRIVATE KEY-----", "")
                    .replaceAll("\\s+", "");

            KeyFactory kf = KeyFactory.getInstance("RSA");
            return kf.generatePrivate(
                    new PKCS8EncodedKeySpec(Base64.getDecoder().decode(privateKey)));
        } catch (NoSuchAlgorithmException e) {
            throw new RuntimeException("当前Java环境不支持RSA", e);
        } catch (InvalidKeySpecException e) {
            throw new RuntimeException("无效的密钥格式");
        }
    }


    /**
     * 开发者应使用商户私钥对下行的敏感信息的密文进行解密
     * @param ciphertext 加密字符串
     * @param privateKey 服务商私钥
     * @return 解密后的字符串
     * @throws BadPaddingException 异常
     * @throws IOException 异常
     */
    public static String rsaDecryptOAEP(String ciphertext, PrivateKey privateKey)
            throws BadPaddingException, IOException {
        try {
            Cipher cipher = Cipher.getInstance("RSA/ECB/OAEPWithSHA-1AndMGF1Padding");
            cipher.init(Cipher.DECRYPT_MODE, privateKey);

            byte[] data = Base64.getDecoder().decode(ciphertext);
            return new String(cipher.doFinal(data), "utf-8");
        } catch (NoSuchPaddingException | NoSuchAlgorithmException e) {
            throw new RuntimeException("当前Java环境不支持RSA v1.5/OAEP", e);
        } catch (InvalidKeyException e) {
            throw new IllegalArgumentException("无效的私钥", e);
        } catch (BadPaddingException | IllegalBlockSizeException e) {
            throw new BadPaddingException("解密失败");
        }
    }

}
